﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

namespace AutoUpdater.Util
{
    public class XElementSetting
    {
        private XElement xe;
        private string path;

        private string keyName = "key";
        private string valueName = "value";
        private string nodeName = "node";
        private string dateTimeStr = "yyyy-MM-dd HH:mm:ss.fff";
        public bool Encode = false;


        private Dictionary<string, string> dictionary = new Dictionary<string, string>();

        public XElementSetting(string fileName, bool encode=false)
        {
            try
            {
                Encode = encode;

                Assembly assembly = Assembly.GetExecutingAssembly();
                //获取项目文件的路径
                //获取项目文件的路径
                string di = assembly.Location.Substring(0, (assembly.Location.LastIndexOf("\\", StringComparison.Ordinal) + 1)) +
                       "\\Setting\\";

                if (!Directory.Exists(di))
                {
                    Directory.CreateDirectory(di);
                }

                path = di + fileName;

                if (!File.Exists(path))
                {
                    xe = new XElement("XmlSetting");
                    Insert("test", "test");
                }
                else
                {
                    xe = XElementAchieve.GetXml(path, Encode) ?? new XElement("XmlSetting");
                }
            }
            catch (Exception exception)
            {
                //如果出现异常,说明文件被损坏 (需要使用文件流的方式在读一次)
                //ExceptionHelperTp.HandleException2(exception);
                xe = new XElement("XmlSetting");
            }
            
        }

        private string GetStringValue(string key)
        {
            if (!dictionary.ContainsKey(key))
            {
                IEnumerable<XElement> element = from ele in xe.Elements(nodeName)
                                                let xAttribute = ele.Attribute("key")
                                                where xAttribute != null && xAttribute.Value == key
                                                select ele;

                IEnumerable<XElement> xElements = element as XElement[] ?? element.ToArray();

                XAttribute result = null;

                if (xElements.Count() == 0)
                {
                    return null;
                }

                if (xElements.Count() > 1)
                {
                    while (xElements.Count() > 1)
                    {
                        xElements.First().Remove();
                    }

                    XElementAchieve.SaveXml(xe, path, Encode);
                }

                result = xElements.First().Attribute(valueName);

                if (result != null)
                {
                    return result.Value;
                }
                return null;
            }
            return dictionary[key];
        }

        public void Insert(string key, string value)
        {
            XElement record = new XElement(
                new XElement(nodeName,
                    new XAttribute(keyName, key),
                    new XAttribute(valueName, value)));
            xe.Add(record);
            XElementAchieve.SaveXml(xe, path, Encode);

            if (!dictionary.ContainsKey(key))
            {
                dictionary.Add(key, value);
            }
        }

        public void Update(string key, string value)
        {
            IEnumerable<XElement> element = from ele in xe.Elements(nodeName)
                                            let xAttribute = ele.Attribute(keyName)
                                            where xAttribute != null && xAttribute.Value == key
                                            select ele;

            IEnumerable<XElement> xElements = element as XElement[] ?? element.ToArray();

            if (!xElements.Any())
            {
                Insert(key, value);
            }
            else
            {
                foreach (XElement xElement in xElements)
                {
                    xElement.SetAttributeValue(valueName, value);
                }
            }

            XElementAchieve.SaveXml(xe, path, Encode);

            if (!dictionary.ContainsKey(key))
            {
                dictionary.Add(key, value);
            }
            else
            {
                dictionary[key] = value;
            }
        }

        public int GetInt(string key)
        {
            string value = GetStringValue(key);

            if (string.IsNullOrEmpty(value))
            {
                Update(key, "0");
                return 0;
            }

            return int.Parse(value);
        }

        public float Getfloat(string key)
        {
            string value = GetStringValue(key);

            if (string.IsNullOrEmpty(value))
            {
                Update(key, "0");
                return 0;
            }

            return float.Parse(value);
        }

        public string GetString(string key)
        {
            string value = GetStringValue(key);

            if (value == null)
            {
                Update(key, "");
            }
            return value;
        }

        public bool GetBool(string key)
        {
            string value = GetStringValue(key);

            if (string.IsNullOrEmpty(value))
            {
                Update(key, "False");
                return false;
            }
            return bool.Parse(value);
        }

        public DateTime GetDateTime(string key)
        {
            DateTime time = DateTime.Now;
            string value = GetStringValue(key);

            if (string.IsNullOrEmpty(value))
            {
                Update(key, time.ToString(dateTimeStr));
                return time;
            }

            return DateTime.Parse(value);
        }
    }
}